from PyQt4.QtCore import *
from PyQt4.QtGui import *

import edge

handleW = 15
handleH = 15


class Handle(QGraphicsEllipseItem):
    def __init__(self,x,y,parent):
        QGraphicsEllipseItem.__init__(self,-handleW/2.0,-handleH/2.0,handleW,handleH,parent)
        self.setPos(x,y)
        self.setZValue(4)
        self.setPen(QPen(Qt.NoPen))
        self.setBrush(QBrush(QColor(Qt.black)))
    def mousePressEvent(self,event):
        startPos = self.scenePos()
        self.edgeDraw = edge.EdgeLine(self,startPos,event.scenePos())
        self.scene().addItem(self.edgeDraw)
        #QGraphicsItem.mousePressEvent(self,event)
    def mouseMoveEvent(self,event):
        newPos = self.mapToScene(event.pos())
        self.edgeDraw.movedTo(self,newPos)
        over = self.scene().items(event.scenePos())
        if over:
            hPos = event.screenPos()
            QToolTip.showText(QPoint(hPos.x(),hPos.y()),over[0].toolTip())
        QGraphicsItem.mouseMoveEvent(self,event)
    def mouseReleaseEvent(self,event):
        overs = self.scene().items(event.scenePos())
        overs = filter(lambda x: isinstance(x,Handle), overs)
        if not overs:
            self.scene().statusBar.showMessage("not over anything")
            self.edgeDraw.hide()
        else:
            over = overs[0]
            if not isinstance(over,Handle):
                self.edgeDraw.hide()
            else:
                if over.canAccept(self):
                    newEdge = edge.Edge(self,over)
                    command = edge.CommandAddEdge(self.scene(),newEdge)
                    self.scene().undoStack.push(command)
                self.edgeDraw.hide()

        QGraphicsItem.mouseReleaseEvent(self,event)

    def canAccept(self,Source):
        """ can this handle accept a link from Source handle? """
        if self.direction == Source.direction:
            self.scene().statusBar.showMessage("links must be in-out",2000)
            return False
        if self.parentItem() == Source.parentItem():
            self.scene().statusBar.showMessage("cant link to self",2000)
            return False
        (src,sink) = (Source,self)
        # if we came from an output:
        if src.direction == -1:
            (src,sink) = (sink,src)
        g = self.scene().graph
        if g.incidents(sink):
            self.scene().statusBar.showMessage("input already has link",2000)
            return False
        if g.has_edge(src,sink):
            self.scene().statusBar.showMessage("this link exists",2000)
            return False
        g.add_edge(src,sink)
        if g.find_cycle():
            self.scene().statusBar.showMessage("adding link would make a cycle",2000)
            g.del_edge(src,sink)
            return False
        self.scene().statusBar.showMessage("edge added",2000)
        g.del_edge(src,sink)
        return True

class Inputs(Handle):
    def __init__(self,x,y,name,parent):
        Handle.__init__(self,x,y,parent)
        self.setBrush(QBrush(QColor(Qt.red)))
        self.setToolTip(name)
        self.name = name
        self.value = None
        self.direction = -1
    def process(self):
        """ get any value from the output handle it is linked to """
        g = self.scene().graph
        connection = g.incidents(self)
        if connection:
            self.value = connection[0].value
            
    def __repr__(self):
        return "Input Handle: "+self.name

class Outputs(Handle):
    def __init__(self,x,y,name,parent):
        Handle.__init__(self,x,y,parent)
        self.setBrush(QBrush(QColor(Qt.green)))
        self.setToolTip(name)
        self.name = name
        self.value = None
        self.direction = +1
    def process(self):
        """ the operator will set the value of the input handle """
        pass
    def __repr__(self):
        return "Output Handle: "+self.name




